window: Use subsurfaces for popovers on wayland
authorCarlos Garnacho <carlosg@gnome.org>
Mon, 20 Oct 2014 17:10:52 +0000 (19:10 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Tue, 23 Dec 2014 12:55:24 +0000 (13:55 +0100)
On the wayland backend, set up GDK_WINDOW_SUBSURFACE windows
for popovers. In the popover code, the popover-relative-to-parent
calculation had to be tweaked, and it's been made to always prefer
the given popover position, since there's no sizing limitations.

https://bugzilla.gnome.org/show_bug.cgi?id=738891

gtk/gtkpopover.c
gtk/gtkwindow.c

index 8627ca84c49a9dbce09760832a0e9539b2c473ec..0fbbd5a50a6b15f7a8672912548a62bc45617490 100644 (file)
 #include "a11y/gtkpopoveraccessible.h"
 #include "gtkmenusectionbox.h"
 
+#ifdef GDK_WINDOWING_WAYLAND
+#include "wayland/gdkwayland.h"
+#endif
+
 #define TAIL_GAP_WIDTH 24
 #define TAIL_HEIGHT    12
 
@@ -523,8 +527,24 @@ gtk_popover_get_gap_coords (GtkPopover      *popover,
 
   gtk_popover_get_pointing_to (popover, &rect);
   gtk_widget_get_allocation (widget, &allocation);
-  gtk_widget_translate_coordinates (priv->widget, widget,
-                                    rect.x, rect.y, &rect.x, &rect.y);
+
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    {
+      gint win_x, win_y;
+
+      gtk_widget_translate_coordinates (priv->widget, GTK_WIDGET (priv->window),
+                                        rect.x, rect.y, &rect.x, &rect.y);
+      gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (popover)),
+                             &win_x, &win_y);
+      rect.x -= win_x;
+      rect.y -= win_y;
+    }
+  else
+#endif
+    gtk_widget_translate_coordinates (priv->widget, widget,
+                                      rect.x, rect.y, &rect.x, &rect.y);
+
   get_margin (widget, &margin);
 
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
@@ -802,7 +822,11 @@ gtk_popover_update_position (GtkPopover *popover)
   overshoot[GTK_POS_LEFT] = req.width - rect.x;
   overshoot[GTK_POS_RIGHT] = rect.x + rect.width + req.width - window_alloc.width;
 
-  if (overshoot[pos] <= 0)
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    {
+      priv->final_position = priv->preferred_position;
+    }
+  else if (overshoot[pos] <= 0)
     {
       priv->final_position = priv->preferred_position;
     }
index 8394fc4546a1c9e2b32182b5560621391a5664dc..0fc90293e837829edb0f570fd096d7e9207602f0 100644 (file)
@@ -6319,7 +6319,19 @@ popover_realize (GtkWidget        *widget,
 
   popover_get_rect (popover, window, &rect);
 
-  attributes.window_type = GDK_WINDOW_CHILD;
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    {
+      attributes.window_type = GDK_WINDOW_SUBSURFACE;
+      parent_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+    }
+  else
+#endif
+    {
+      attributes.window_type = GDK_WINDOW_CHILD;
+      parent_window = gtk_widget_get_window (GTK_WIDGET (window));
+    }
+
   attributes.wclass = GDK_INPUT_OUTPUT;
   attributes.x = rect.x;
   attributes.y = rect.y;
@@ -6330,10 +6342,15 @@ popover_realize (GtkWidget        *widget,
     GDK_EXPOSURE_MASK;
   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
-  parent_window = gtk_widget_get_window (GTK_WIDGET (window));
   popover->window = gdk_window_new (parent_window, &attributes, attributes_mask);
   gtk_widget_register_window (GTK_WIDGET (window), popover->window);
 
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    gdk_window_set_transient_for (popover->window,
+                                  gtk_widget_get_window (GTK_WIDGET (window)));
+#endif
+
   gtk_widget_set_parent_window (popover->widget, popover->window);
 }
 
@@ -7123,6 +7140,11 @@ popover_unrealize (GtkWidget        *widget,
                    GtkWindowPopover *popover,
                    GtkWindow        *window)
 {
+#ifdef GDK_WINDOWING_WAYLAND
+  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget)))
+    gdk_window_set_transient_for (popover->window, NULL);
+#endif
+
   gtk_widget_unregister_window (GTK_WIDGET (window), popover->window);
   gtk_widget_unrealize (popover->widget);
   gdk_window_destroy (popover->window);